package com.xunfang.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import java.util.Date;
import java.util.Map;

/**
 * JWT 工具类（基于 JJWT 0.12.6+）
 * 支持生成、解析、验证 JWT Token
 */
@Slf4j
@Component
public class JwtUtils {

    // 签名密钥（生产环境建议从配置文件或环境变量读取）
    private static final String SECRET_STRING = "k3j9a8s7d6f5g4h3j2k1l9o8i7u6y5t4r3e2w1q0p9o8i7u6y5t4r3e2w1q0p9o8i7";

    // 过期时间：30 分钟
    private static final long EXPIRATION = 30 * 60 * 1000; // 毫秒

    // 生成密钥（HS256 要求至少 256 位 = 32 字节）
    private static final SecretKey SECRET_KEY = Keys.hmacShaKeyFor(SECRET_STRING.getBytes());

    /**
     * 生成 JWT Token
     * @param  payLoad    自定义载荷（如 userId, role）
     * @return JWT Token
     */
    public static String generateToken(Map<String, Object> payLoad) {
        Date now = new Date();
        Date expirationDate = new Date(now.getTime() + EXPIRATION);

        return Jwts.builder()
                .header()
                    .add("typ", "JWT")
                    .add("alg", "HS256")
                    .and()
                .subject("book-mall-system")
                .issuedAt(now)
                .expiration(expirationDate)
                .claims(payLoad)  // 添加自定义字段
                .signWith(SECRET_KEY, Jwts.SIG.HS256) // 签名
                .compact();
    }

    /**
     * 解析 JWT Token，返回所有 Claims
     * @param token JWT Token
     * @return Claims 对象
     * @throws JwtException 如果 Token 无效（过期、篡改等）
     */
    public static Jws<Claims> parseToken(String token) throws JwtException {
        return Jwts.parser()
                .verifyWith(SECRET_KEY)
                .build()
                .parseSignedClaims(token);
    }

    /**
     * 获取 Token 中的指定字段（如 userId, role）
     * @param token JWT Token
     * @param key 字段名
     * @return 字段值，如果不存在则返回 null
     */
    public static String getValue(String token, String key) {
        try {
            //解析Token，判断Token是否合法
            Jws<Claims> claimsJws = parseToken(token);
            //获取载荷
            Claims claims = claimsJws.getBody();
            //获取指定的值
            return claims.get(key).toString();
        } catch (JwtException e) {
            return null;
        }
    }

    /**
     * 验证 Token 是否有效（未过期且签名正确）
     * @param token JWT Token
     * @return true 如果有效
     */
    public static boolean validateToken(String token) {
        //直接调用上面的方法进行解析
        try {
            parseToken(token);
            return true;
        } catch (Exception e) {
            log.info("验证Token失败:{}", e.getMessage());
            return false;
        }
    }
    
}